import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { UserEntity } from "../entities/user.entity";
import { UserAuthService } from "./user-auth.service";
import { randomBytes, createHash } from "crypto";

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(UserEntity)
    private readonly userRepo: Repository<UserEntity>,
    private readonly userAuthService: UserAuthService
  ) { }

  async findByMobile(mobile: string): Promise<UserEntity | null> {
    return this.userRepo.findOne({ where: { mobile } });
  }

  async findById(id: number): Promise<UserEntity | null> {
    return this.userRepo.findOne({ where: { id } });
  }

  async findAllUsers(): Promise<UserEntity[]> {
    return this.userRepo.find();
  }

  async register(
    mobile: string,
    passwordHash: string,
    channel?: string | null,
    inviteCode?: string | null
  ): Promise<UserEntity> {
    const exist = await this.findByMobile(mobile);
    if (exist) throw new Error("MOBILE_EXISTS");
    const user = this.userRepo.create({
      mobile,
      passwordHash,
      channel: channel || null,
      inviteCode: inviteCode || null,
      created_at: new Date(),
    });
    return this.userRepo.save(user);
  }

  async login(
    mobile: string,
    passwordHash: string
  ): Promise<{ user: UserEntity; token: string } | null> {
    const user = await this.findByMobile(mobile);
    if (!user) return null;
    if (user.passwordHash !== passwordHash) return null;

    const token = this.generateToken();

    // 将token信息存储在Redis缓存中
    await this.userAuthService.storeUserToken(user, token);

    return { user, token };
  }

  async validateToken(userId: number, token: string): Promise<boolean> {
    // 使用UserAuthService来验证token
    return await this.userAuthService.validateToken(token);
  }

  async resetPassword(mobile: string, passwordHash: string): Promise<boolean> {
    const user = await this.findByMobile(mobile);
    if (!user) return false;
    user.passwordHash = passwordHash;
    user.updated_at = new Date();
    await this.userRepo.save(user);
    return true;
  }

  private generateToken(): string {
    // 32位十六进制（与示例一致）
    return createHash("md5").update(randomBytes(32)).digest("hex");
  }
}
